package org.zjt.platform.demo.config;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author <a href="juntao.zhang@qq.com">juntao.zhang</a>
 * @Description:
 * @Package org.zjt.platform.demo.config
 * @date 2018/3/12 11:41
 * @see
 */
@Configuration
@EnableAspectJAutoProxy
@Aspect
@SuppressWarnings("all")
@Slf4j
public class AspectConfiguration {


    private static final Map<String,AtomicLong> ACCESS_COUNT=new ConcurrentHashMap<>();
    private static final String PACKAGE_SEPARATOR=".";


	@Around("execution(* org.zjt.platform.demo.service..*.*(..))")
	public Object around(ProceedingJoinPoint joinpoint)throws java.lang.Throwable{
	    Long startTime=System.currentTimeMillis();
        Object[] args = joinpoint.getArgs();
        Object result=joinpoint.proceed(args);
        String methodName=joinpoint.getSignature().getName();
        String DeclaringTypeName=joinpoint.getSignature().getDeclaringTypeName();
        Long endTime=System.currentTimeMillis();
        if(!ACCESS_COUNT.containsKey(DeclaringTypeName+PACKAGE_SEPARATOR+methodName))
            ACCESS_COUNT.putIfAbsent(DeclaringTypeName+PACKAGE_SEPARATOR+methodName,new AtomicLong(1));  //同步的
        else
            ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).incrementAndGet();
        log.info(String.format("执行%s.%s()  参数:%s  耗时:%s（毫秒）  第%s次调用",DeclaringTypeName,methodName, JSONObject.toJSONString(args),(endTime-startTime),ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).get()));
        if (endTime-startTime > 1000)
            log.error(String.format("执行%s.%s()  参数:%s  耗时:%s（毫秒）  第%s次调用",DeclaringTypeName,methodName, JSONObject.toJSONString(args),(endTime-startTime),ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).get()));
        return result;
	}

    //抛出异常后处理
    @AfterThrowing(throwing="ex",pointcut="execution(* org.zjt.platform.demo.service..*.*(..))")
    public void AfterExcepter(Throwable ex){
        log.error("执行方法出错",ex);
    }

}